package com.vito.demo.kotlin

/**
 * Created by lingzhiyuan.
 * Date : 16/3/28.
 * Time : 下午9:46.
 * Description:
 *
 * kotlin basic grammar demos
 *
 */

// 带有两个 Int 参数、返回 Int 的函数:
fun sumA(a: Int, b: Int): Int {
    return a + b;
}

// 将表达式作为函数体、返回值类型自动推断的函数:
fun sumB(a: Int, b: Int) = a + b;

// 函数返回无意义的值:
fun printSumA(a: Int, b: Int): Unit {
    print(a + b);
}

// Unit 返回类型可以省略:
fun printSumB(a: Int, b: Int) {
    print(a + b);
}

// 常量(使用 val 关键字声明):
fun constant() {
    val a: Int = 1
    val b = 1 // `Int` 类型自动推断
    val c: Int // 如果没有初始值,声明常量时,常量的类型不能省略
    c = 1 // 明确赋值
}

// 变量(使用 var 关键字声明):
fun variable() {
    var x: Int = 5
    var y = 5 // `自动推断出 Int` 类型
    x += 1
}

// 使用字符串模板
fun stringTemplate(params: Array<String>) {
    if (params.size == 0) {
        return
    }

    print("First param: ${params[0]}")
}

// 使用条件判断
fun maxA(a: Int, b: Int): Int {
    if (a > b) {
        return a
    }
    else {
        return b
    }
}

// 使用 if 作为表达式:
fun maxB(a: Int, b: Int) = if (a > b) a else b

// 当某个变量的值可以为 null 的时候,必须在声明处的类型后添加 ? 来标识该引用可为空。
// 如果 str 的内容不是数字返回 null:
fun parseInt(str: String): Int? {
    return try {
        Integer.parseInt(str)
    }
    catch(ex: Exception) {
        throw IllegalArgumentException();
    };
}

// 返回可空值的函数:
fun returnNullA(params: Array<String>) {
    if (params.size < 2) {
        print("Two Integers Expected")
        return
    }

    val x = parseInt(params[0])
    val y = parseInt(params[1])

    // 直接使用 `x * y` 可能会报错,因为他们可能为 null
    if (x != null && y != null) {
        // 在空指针判断后,x 和 y 会自动转换为非空值(non-nullable)
        print(x * y)
    }
}

// is 运算符用于类型判断: 检查某个实例是否是某类型。
// 如果一个局部常量或者不可变的类成员变量已经判断出为某 类型,那么判断后的分支中可以直接当作该类型使用,无需显式转换
fun getStringLengthA(obj: Any): Int? {
    if (obj !is String) {
        // `obj` 在该条件判断分支内自动转换成 `String`
        return null
    }
    // 在离开类型判断分支后, `obj` 仍然是 `Any` 类型
    return obj.length
}

fun getStringLengthB(obj: Any): Int? {
    // `obj` 在 `&&` 右边自动转换成 `String` 类型
    if (obj is String && obj.length > 0) {
        return obj.length
    }
    return null
}

fun getStringLengthC(obj: Any): Int? {
    if (obj !is String) {
        return null
    }
    // `obj` 在这一类型判断分支自动转换为 `String`
    return obj.length
}

// 使用 for 循环:
fun forLoopA(params: Array<String>) {
    for (param in params) print(param)
}

fun forLoopB(params: Array<String>) {
    for (index in params.indices) print(params[index])
}

// 使用while循环
fun whileLoop(params: Array<String>) {
    var index = 0
    while (index < params.size) {
        print(params[index ++])
    }
}

// 使用when表达式
fun cases(obj: Any) {
    when (obj) {
        1          -> print("One")
        "hello"    -> print("Greeting")
        is Long    -> print("Long Number")
        !is String -> print("Not a String")
        else       -> print("Unknown")
    }
}

// 使用区间
// 使用 in 运算符来检查某个数字是否在指定区间内:
fun useRangeA(num: Int, min: Int, max: Int): Unit {
    if (num in min .. max) {
        print("OK")
    }
    else {
        print("NO")
    }
}

// 检查某个数字是否在指定区间外:
fun useRangeB(num: Int, min: Int, max: Int): Unit {
    if (num !in min .. max) {
        print("OK")
    }
    else {
        print("NO")
    }
}

// 区间内迭代:
fun useRangeC(min: Int, max: Int): Unit {
    for (index in min .. max) {
        print("$index ")
    }
}

// 使用集合:
// 对集合进行迭代:
fun useCollectionA(names: Array<String>): Unit {
    for (name in names) {
        println(name);
    }
}

// 使用 in 运算符来判断集合内是否包含某实例:
fun useCollectionB(name: String, names: Array<String>): Unit {
    if (name in names) {
        print("yes")
    }
    else {
        print("no")
    }
}

// 使用 lambda 表达式来过滤(filter)和变换(map)集合:
fun useCollectionC(names: Array<String>): Unit {
    names
            .filter { it.contains("i") }
            .sortedBy { it }
            .map { it.toUpperCase() }
            .forEach { print(it) }
}







